package com.sajus.web.billing.ejb.domain;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import com.sajus.web.billing.ejb.data.model.PersistentObject;
import com.sajus.web.billing.ejb.data.model.TransactionContext;


public class SyncList<E extends DomainObject> extends ArrayList<E> {
	
	private List<PersistentObject> originalList;

	public SyncList(Class<E> cls, Class<?> delegateCls, List<PersistentObject> originalList) {
		if (originalList == null) {
			throw new IllegalArgumentException( "Original List cannot be null");
		}
		
		this.originalList = originalList;
		try {
			Constructor<E> ctor = cls.getConstructor(delegateCls);
			for (PersistentObject persistentObject : originalList) {
				E instance =ctor.newInstance( persistentObject );
				super.add( instance );
			}
		} catch(Throwable t) {
			
		}
	}


	@Override
	public boolean add(E e) {
		this.originalList.add( e.getDelegate() );
		return super.add(e);
	}

	@Override
	public void add(int index, E e) {
		this.originalList.add(index,  e.getDelegate() );
		super.add(index, e);
	}

	@Override
	public void clear() {
		Iterator it = this.originalList.iterator();
		try {
		while(it.hasNext()) {
			PersistentObject obj = (PersistentObject)it.next();			
			obj.remove();
			it.remove();
		}} catch (Throwable t) {
			t.printStackTrace();
		}
		super.clear();
		TransactionContext.getTransactionContext().getEm().flush();
	}

	@Override
	public boolean remove(Object o) {
		DomainObject obj = (DomainObject)o;
		/* remove it from the original list */
		this.originalList.remove( obj.getDelegate() );
		/* remove it from the entity manager */
		obj.getDelegate().remove();
		return super.remove(o);
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		for (Object object : c) {
			this.remove( object );
		}
		return true;
	}

	@Override
	public boolean addAll(Collection<? extends E> c) {
		for (E e : c) {
			this.add(e);
		}
		return true;
	}

	/**
	 * this is called by the iterator remove method 
	 * maybe implement the SyncIterator later to avoid possible problems 
	 * with changes in the iterator impl
	 */
	@Override
	public E remove(int index) {
		DomainObject obj = (DomainObject) this.get( index );
		/* remove it from the original list */
		this.originalList.remove( obj.getDelegate() );
		/* remove it from the entity manager */
		obj.getDelegate().remove();
		return super.remove(index);
	}
	
}
